<?php
/*
 * Darek
 */

require_once 'wezel.php';
require_once 'bazaDanych.php';

class Drzewo
{
	private $korzen;
	private $tablica;
	private $wiersze;			//ilość wierszy (i)
	private $kolumny;			//ilość kolumn (j)
	private $maxRekurencji=100; //maksymalna ilość wywołań metody rekurencyjnej

	public function getKorzen() { return $this->korzen; }
	
	/*//wersja wyświetlająca jeden węzeł
	public function __construct($id_wezla)
	{
		$baza=new BazaDanych();
		$this->korzen = $baza->zwrocWezel($id_wezla);
	}
	
	public function naHtml($ogladajacy='admin')
	{
		if($this->korzen!==null)
		{
			$w=$this->korzen->naHtml($ogladajacy);
			
			return $w;
		}
		else
			return 'Nie znaleziono węzla o podanym ID w bazie danych';
	}//*/
	
	
	public function __construct($id_wezla)
	{
		$wiersze=0;
		$kolumny=0;
		$baza=new BazaDanych();
		$this->korzen=$baza->zwrocKorzen($id_wezla);
		if($this->korzen!==null)
		{	
		//dodanie dzieci
			//dzieci są przypisane w strukturze do ojca, więc trzeba sprawdzić, czy kobieta ma męża
			if($this->korzen->getOsoba()->getPlec())
				$this->dodajDzieci($this->korzen, $baza);
			else
				if($this->korzen->getPartner()!==null)
					$this->dodajDzieci($this->korzen->getPartner(), $baza);
			
		//przekształcenie drzewa na tabelę w celu wyświetlenia
			$this->kolumny=2*$this->tworzTablice(0, 0, $this->korzen);	//wynik wierszy i kolumn mnożony jest przez 2, bo między wierszami i kolumnami są linie
			$this->wiersze=2*($this->wiersze+1);			//liczba wierszy jest zaniżona o jeden, więc trzeba dodać jeden
			for($j=0; $j<$this->kolumny; $j+=2)				//wstawienie elementów regulujących odsŧępy między węzłami
				$this->tablica[0][$j+1]=new Linia('X');
		}
	}
	
	public function naHtml($ogladajacy='admin')
	{
		if($this->korzen!==null)
		{
			$w= '<table class="tablica">';
			for($i=0; $i<$this->wiersze; $i++)
			{
				$w.= '<tr>';
				for($j=0; $j<$this->kolumny; $j++)
				{
					//$w.= '<td>';
					if(isset($this->tablica[$i][$j]))
					{
						if($this->tablica[$i][$j] instanceof Linia)
							$w.=$this->tablica[$i][$j]->naHtml($ogladajacy);
						else
						{
							$w.='<td style="vertical-align: top; horizontal-align: center;">';
							$w.= $this->tablica[$i][$j]->naHtml($ogladajacy);
							$w.='</td>';
						}
					}
						
					else 
						$w.= '<td></td>';
				}
				$w.= '</tr>';
			}
			$w.= '</table>';
					return $w;
		}
		else
							return '<p>Nie znaleziono węzla o podanym ID w bazie danych</p>';
	}//*/
	
	/*
	 * metoda rekurencyjna tworząca tablicę z węzłami w celu późniejszego wyświetlenia
	 * $i - wiersz początkowy
	 * $j - kolumna początkowa
	 * $we - obecnie przetwarzany Węzeł
	 */
	private function tworzTablice($i, $j, Wezel $we)
	{
		$maxj=$j;
		
		if($i>$this->wiersze)
			$this->wiersze=$i;		//przypisanie aktualnej liczby wierszy (pomniejszone o jeden)

		
		$this->tablica[$i*2+1][$maxj*2]=$we;						//i*2+1, bo nad węzłem będą linie prowadzące do rodziców i trzeba im zostawić miejsce
		$maxj++;
		
		if($we->getPartner()!==null && $i<$this->maxRekurencji)		//i<maxRekurencji - zabezpieczenie przed zapętleniem rekurencji
		{
			$this->tablica[$i*2+1][$maxj*2]=$we->getPartner();
			$maxj++;
			if($we->getOsoba()->getPlec())		//jeśli mężczyzna
				$dzie=$we->getDzieci();
			else 								//jeśli kobieta to wybierz dzieci przypisane w strukturze do partnera
				$dzie=$we->getPartner()->getDzieci();
			
			$ilDzieci=count($dzie);
			
			
		//LINIE dodanie linii łączącej męża i żonę
			if($ilDzieci>0)
				$this->tablica[$i*2+1][($maxj-1)*2-1]=new Linia('pT');
			else
				$this->tablica[$i*2+1][($maxj-1)*2-1]=new Linia('p-');
		//Koniec Linii
			
			for($l=0; $l<$ilDzieci; $l++)
			{	
				$ostj=$j;
					
				$j=$this->tworzTablice($i+1, $j, $dzie[$l]);		//wywołanie rekurencyjne
				if($j>$maxj)
					$maxj=$j;
				
			//LINIE dodanie linii łączących dzieci z rodzicami
				if($l==0)									//pierwsze dziecko
				{
					$this->tablica[($i+1)*2][$ostj*2]=new Linia('F');
					if($ilDzieci>1)					//jeśli jest więcej dzici to narysuj całą linię, jeśli nie to połówkę
					{
						$this->tablica[($i+1)*2][$ostj*2+1]=new Linia('-');
						$ostj++;
						for($o=$ostj; $o<$j; $o++)
						{
							$this->tablica[($i+1)*2][$o*2]=new Linia('-');
							$this->tablica[($i+1)*2][$o*2+1]=new Linia('-');
						}
						
					}
					else 
						$this->tablica[($i+1)*2][$ostj*2+1]=new Linia('-/2');
				}
				else if($l==$ilDzieci-1 && $ilDzieci>1)		//ostatnie dziecko
				{
					$this->tablica[($i+1)*2][$ostj*2]=new Linia('7');
				}
				else										//środkowe dziecko
				{
					$this->tablica[($i+1)*2][$ostj*2]=new Linia('T');
					$this->tablica[($i+1)*2][$ostj*2+1]=new Linia('-');
					$ostj++;
					for($o=$ostj; $o<$j; $o++)
					{
						$this->tablica[($i+1)*2][$o*2]=new Linia('-');
						$this->tablica[($i+1)*2][$o*2+1]=new Linia('-');
					}
				}
			//Konie Linii
				
			}
		}
		
		return $maxj;
	}
	
	private function dodajDzieci(Wezel $we, BazaDanych $baza, $licznikRekurencji=0)
	{
		$dzieci=$baza->zwrocDzieci($we->getId());
		
		if($licznikRekurencji<$this->maxRekurencji)			//zabezpieczenie przed zapętleniem rekurencyjnym
		{
			foreach($dzieci as $dz)
			{
				//dzieci są przypisane w strukturze do ojca, więc trzeba sprawdzić, czy kobieta ma męża
				if($dz->getOsoba()->getPlec())
					$this->dodajDzieci($dz, $baza, $licznikRekurencji+1);
				else
					if($dz->getPartner()!==null)
					$this->dodajDzieci($dz->getPartner(), $baza, $licznikRekurencji+1);
			
				$we->add($dz);
			}
		}
		else 
			echo '<p>Przekroczono '.$this->maxRekurencji.' wywołań metody rekurencyjnej</p>';
		
	}

}

class Linia
{
	private $typ;
	/*
	 * dopuszczalne wartości typu: 
	 * 		'F' '-' '-/2' 'T' '7' dla linii nad węzłami prowadzącymi do rodziców
	 * 		'p-' 'pT' dla linii pomiędzy węzłami męża i żony
	 * 		'X' - element pusty, regulujący odstęp między węzłami
	 * 
	 */
	public function __construct($typ)
	{
		$this->typ=$typ;
	}
	
	public function naHtml()
	{
		$w='';
		if($this->typ=='F')
			$w.='<td class="liniaF linia"></td>';
		else if($this->typ=='-')
			$w.='<td class="linia- linia"></td>';
		else if($this->typ=='-/2')
			$w.='<td class="linia-2 linia"></td>';
		else if($this->typ=='T')
			$w.='<td class="liniaT linia"></td>';
		else if($this->typ=='7')
			$w.='<td class="linia7 linia"></td>';
		else if($this->typ=='p-')
			$w.='<td class="liniap-"></td>';
		else if($this->typ=='pT')
			$w.='<td class="liniapT"></td>';
		else if($this->typ=='X')
			$w.='<td class="miedzyWezlami"><div class="miedzyWezlami"></div></td>';
		else 
			$w.='';
		
		return $w;
	}
}
?>